﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data.SqlClient;
using System.Configuration;
using System.Data;

namespace Mantenimiento.CAD
{
    public class dbManager : IDisposable
    {
        #region Variables privadas

        private SqlConnection m_Connection;
        private string m_ConnectionString;
        private string m_Servidor;
        private string m_BD;
        private string m_Usuario;
        private string m_Password;
        private SqlDataAdapter m_DataAdapter;
        private DataSet m_Datos;
        private SqlCommand m_Command;

        #endregion

        #region Constructores

        public dbManager()
        {
            m_Connection = null;
            m_ConnectionString = ConfigurationManager.AppSettings["Servidor_SQL_ConnString"];
            m_Servidor = ConfigurationManager.AppSettings["Servidor_SQL"];
            m_BD = ConfigurationManager.AppSettings["BD_SQL"];
            m_Usuario = ConfigurationManager.AppSettings["Usuario_SQL"];
            m_Password = ConfigurationManager.AppSettings["Password_SQL"];
            m_DataAdapter = null;
            m_Datos = null;
            m_Command = null;
        }

        public dbManager(string Servidor, string BD, string Usuario, string Password)
        {
            m_Connection = null;
            m_ConnectionString = "";
            m_Servidor = Servidor;
            m_BD = BD;
            m_Usuario = Usuario;
            m_Password = Password;
            m_DataAdapter = null;
            m_Datos = null;
            m_Command = null;
        }

        #endregion

        #region Destrucción de objetos

        // Método, heredado del interfaz IDisposable, en el que liberamos la memoria
        public void Dispose()
        {
            this.Desconectar();

            m_DataAdapter = null;
            m_Datos = null;
            m_Command = null;

            GC.Collect();
        }

        #endregion

        #region Métodos

        // Método para conectar con la base de datos, siempre y cuando las propiedades de conexión ya hayan sido establecidas
        public bool Conectar()
        {
            //this.m_ConnectionString = "Password=" + m_Password + ";Persist Security Info=True;User ID=" + m_Usuario + ";Initial Catalog=" +
            //    m_BD + ";Data Source=" + m_Servidor + ";";


            if (this.m_Connection == null)
                this.m_Connection = new SqlConnection(this.m_ConnectionString);

            if (this.m_Connection.State != ConnectionState.Open)
                this.m_Connection.Open();

            return true;
        }

        // Método para conectar con la base de datos y al mismo tiempo establecer la cadena de conexión
        public bool Conectar(string ConnectionString)
        {
            try
            {
                this.m_ConnectionString = ConnectionString;
                this.m_Connection = new SqlConnection(this.m_ConnectionString);
                this.m_Connection.Open();

                return true;
            }
            catch
            {
                return false;
            }
        }

        // Método para conectar con la base de datos y al mismo tiempo establecer las propiedades de conexión. La cadena de conexión también se
        // establece
        public bool Conectar(string Servidor, string BD, string Usuario, string Password)
        {
            try
            {
                this.m_Servidor = Servidor;
                this.m_BD = BD;
                this.m_Usuario = Usuario;
                this.m_Password = Password;
                this.m_ConnectionString = "Password=" + Password + ";Persist Security Info=True;User ID=" + Usuario + ";Initial Catalog="
                    + BD + ";Data Source=" + Servidor + ";";
                this.m_Connection = new SqlConnection(this.m_ConnectionString);
                this.m_Connection.Open();

                return true;
            }
            catch
            {
                return false;
            }
        }

        // Método para desconectar de la base de datos
        public bool Desconectar()
        {
            try
            {
                if (this.m_Connection != null)
                {
                    if (this.m_Connection.State == ConnectionState.Open)
                    {
                        this.m_Connection.Close();
                        this.m_Connection = null;

                        GC.Collect();
                    }
                }

                return true;
            }
            catch
            {
                return false;
            }
        }

        // Método para ejecutar un procedimiento almacenado y si es necesario, devolver el resultado del mismo
        public object EjecutarSP(string storedProcedure, object[] Parametros)
        {
            int i;
            object salida = null;

            try
            {
                // Si la conexión no está inicializada o abierta, la abrimos
                if (this.m_Connection == null || this.m_Connection.State == ConnectionState.Closed)
                    this.Conectar();

                // Establecemos las propiedades del comando
                this.m_Command = new SqlCommand(storedProcedure, this.m_Connection);
                this.m_Command.CommandType = CommandType.StoredProcedure;

                // Y sus parámetros
                if (Parametros != null)
                {
                    for (i = 0; i < Parametros.Length; i += 2)
                    {
                        this.m_Command.Parameters.AddWithValue(Parametros[i].ToString(), Parametros[i + 1].ToString());
                    }
                }

                // Y lo ejecutamos, recogiendo el valor de salida
                salida = this.m_Command.ExecuteScalar();

                // Volvemos a cerrar la conexión
                if (this.m_Connection.State == ConnectionState.Open)
                    this.Desconectar();

                // Y devolvemos el valor que nos ha devuelto
                return salida;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        // Método para ejecutar un procedimiento almacenado y recoger los datos devueltos por éste en un DataSet
        public DataSet EjecutarSP_DS(string storedProcedure, object[] Parametros)
        {
            int i;

            try
            {
                // Si la conexión no está inicializada o abierta, la abrimos
                if (this.m_Connection == null || this.m_Connection.State == ConnectionState.Closed)
                    this.Conectar();

                // Establecemos las propiedades del comando
                this.m_Command = new SqlCommand(storedProcedure, this.m_Connection);
                this.m_Command.CommandType = CommandType.StoredProcedure;

                // Y sus parámetros
                if (Parametros != null)
                {
                    for (i = 0; i < Parametros.Length; i += 2)
                    {
                        this.m_Command.Parameters.AddWithValue(Parametros[i].ToString(), Parametros[i + 1]);
                    }
                }

                // Y lo ejecutamos, recogiendo en un DataSet los datos que devuelve
                this.m_DataAdapter = new SqlDataAdapter(this.m_Command);
                this.m_Datos = new DataSet();
                this.m_DataAdapter.Fill(this.m_Datos);

                // Volvemos a cerrar la conexión
                if (this.m_Connection.State == ConnectionState.Open)
                    this.Desconectar();

                // Y devolvemos los datos
                return this.m_Datos;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        // Método para ejecutar una sentencia SQL de inserción, actualización o borrado
        public bool EjecutarSQL(string SQL)
        {
            try
            {
                // Si la conexión no está inicializada o abierta, la abrimos
                if (this.m_Connection == null || this.m_Connection.State == ConnectionState.Closed)
                    this.Conectar();

                // Establecemos las propiedades del comando
                this.m_Command = new SqlCommand(SQL, this.m_Connection);
                this.m_Command.CommandType = CommandType.Text;

                // Y lo ejecutamos
                this.m_Command.ExecuteNonQuery();

                // Volvemos a cerrar la conexión
                if (this.m_Connection.State == ConnectionState.Open)
                    this.Desconectar();

                return true;
            }
            catch
            {
                return false;
            }
        }

        // Método para ejecutar una sentencia SQL de selección y recoger los datos devueltos por ésta en un DataSet
        public DataSet EjecutarSQL_DS(string SQL)
        {
            try
            {
                // Si la conexión no está inicializada o abierta, la abrimos
                if (this.m_Connection == null || this.m_Connection.State == ConnectionState.Closed)
                    this.Conectar();

                // Establecemos las propiedades del comando
                this.m_Command = new SqlCommand(SQL, this.m_Connection);
                this.m_Command.CommandType = CommandType.Text;

                // Y lo ejecutamos, recogiendo en un DataSet los datos que devuelve
                this.m_DataAdapter = new SqlDataAdapter(this.m_Command);
                this.m_Datos = new DataSet();
                this.m_DataAdapter.Fill(this.m_Datos);

                // Volvemos a cerrar la conexión
                if (this.m_Connection.State == ConnectionState.Open)
                    this.Desconectar();

                // Y devolvemos los datos
                return this.m_Datos;
            }
            catch
            {
                return null;
            }
        }

        // Método para ejecutar unsa setencia SQL de selección y devolver el valor del primer registro del primer campo devuelto
        public object EjecutarSQL_Escalar(string SQL)
        {
            object resul = null;

            try
            {
                // Si la conexión no está inicializada o abierta, la abrimos
                if (this.m_Connection == null || this.m_Connection.State == ConnectionState.Closed)
                    this.Conectar();

                // Establecemos las propiedades del comando
                this.m_Command = new SqlCommand(SQL, this.m_Connection);
                this.m_Command.CommandType = CommandType.Text;

                // Y lo ejecutamos, recogiendo el valor devuelto
                resul = this.m_Command.ExecuteScalar();

                if (this.m_Connection.State == ConnectionState.Open)
                    this.Desconectar();

                // Devolvemos el resultado
                return resul;
            }
            catch
            {
                return null;
            }
        }

        #endregion
    }
}